package classLoad;
import java.net.URL;
import java.net.MalformedURLException;
import java.io.File;
import java.io.IOException;
import util.GAConfig;
public class MyClassLoader extends ClassLoader{

    public MyClassLoader(ClassLoader parent) {
        super(parent);
    }
    public Class<?> loadClass(String cut,String name) throws ClassNotFoundException {
        if(!cut.equals(name))
                return super.loadClass(name);

        try {
        	URL classURL = searchClassFile(name);
        	if(classURL==null){
        		System.err.print("the instrumented file is not exist!");
        		System.exit(1);
        	}
            byte[] classData = ByteReader.readBytes(classURL.openStream());

            return defineClass(name,classData, 0, classData.length);

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
	private URL searchClassFile(String name)  {
		final String fileName = name.replace('.', File.separatorChar) + ".class";

		File element = GAConfig.getDirInstrumented();

			// if it is a class directory, look for a .class file
			if(element.isDirectory()) {
				File w = new File(element, fileName);
				if(w.exists()) {
					if(w.canRead()) {
						try {
							return w.toURI().toURL();
						} catch (MalformedURLException e) {
							System.err.print("found " + name + " in " + w.getAbsolutePath() + ", but cannot transform to a valid URL"+  e);
						}
					} else {
						System.err.print("found " + name + " in " + w.getAbsolutePath() + ", but cannot read it");
					}
				}
			}
			return null;
	}

    public static void main(String[] args) throws Throwable,
    ClassNotFoundException,
    IllegalAccessException,
    InstantiationException {

    ClassLoader parentClassLoader = MyClassLoader.class.getClassLoader();
    MyClassLoader classLoader = new MyClassLoader(parentClassLoader);
    Class myInstrumentedClass = classLoader.loadClass("lang3.Foo","lang3.Foo");

    Object whatInstance = myInstrumentedClass.newInstance();
    
    System.out.println("");
    String methodParameter = "a quick brown fox";
    
    // Step 5: get the method, with proper parameter signature.
    // The second parameter is the parameter type.
    // There can be multiple parameters for the method we are trying to call,
    // hence the use of array.

//   Method myMethod = myInstrumentedClass.getMethod("m",new Class[] { String.class });
//   myMethod.invoke(null,new Object[] { methodParameter });

    
    // Step 6:
    // Calling the real method. Passing methodParameter as
    // parameter. You can pass multiple parameters based on
    // the signature of the method you are calling. Hence
    // there is an array.
     
 //   myObjectClass = classLoader.loadClass("lang3.Foo");
    
}
}